package job2;

import java.io.*;
import java.lang.reflect.Method;
import java.net.URL;

/**
 * @Description:
 * @Author caorl
 * @Date 2021/3/17
 */
public class HelloClassLoader extends ClassLoader {


    public static void main(String[] args) throws Exception {
        try {
//            System.out.println(System.getProperty("test"));
            Class<?> helloCls = new HelloClassLoader().findClass("Hello");
            Object o = helloCls.newInstance();
            /*for (Method method:helloCls.getMethods()){
                System.out.println(method.getName());
            }*/
            System.out.println(o.getClass().getClassLoader().toString());
            System.out.println(o.getClass().getClassLoader().getParent().toString());
            helloCls.getMethod("hello").invoke(o);
//            Object o = new HelloClassLoader().findClass("job2.Binary").newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    public static byte convertByte(byte b) {
        String byteStr = Integer.toBinaryString((b & 0xFF) + 0x100).substring(1);
        //2.带符号位二进制转int
        Integer i = Integer.valueOf(byteStr, 2);
        //3.255-int(不带符号位的)
        Integer a = 255 - i;
        //4.符号位转机器码保存为byte
        String substring = Integer.toBinaryString((a & 0xFF) + 0x100).substring(1);
        if (substring.startsWith("0")) {
            return Byte.valueOf(a.toString());
        } else {
            String substring1 = Integer.toBinaryString((~a & 0xFF) + 0x100).substring(1);
            int i2 = Integer.parseInt(substring1, 2);
            Integer res = -i2 - 1;
            return Byte.valueOf(res.toString());
        }
    }


    public static byte[] file2byte(File tradeFile) {
        byte[] buffer = null;
        try {
            FileInputStream fis = new FileInputStream(tradeFile);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        URL resource = HelloClassLoader.class.getResource("/Hello.xlass");
//        URL resource = HelloClassLoader.class.getResource("/Hello.class");
        File file = new File(resource.getPath());
        byte[] bytes = file2byte(file);
        return defineClass(name, decode(bytes), 0, bytes.length);
//        return defineClass(name, bytes, 0, bytes.length);
    }

    public static byte[] decode(byte[] bytes) {
        byte[] result = new byte[bytes.length];

        for (int i = 0; i < bytes.length; i++) {
//            System.out.println("currentByte===="+bytes[i]);
            result[i] = convertByte(bytes[i]);
        }
        return result;
    }

    /**
     * 真值：将带符号位的机器数对应的真正数值称为机器数的真值，例：1000 0011，其最高位1代表负，其真正数值是 -3。
     * 原码：上面举例的 1000 0011就是原码
     * 反码：正数的反码是其本身；负数的反码是在其原码的基础上，符号位不变，其余各个位取反
     * 补码：正数的补码就是其本身；负数的补码是在其原码的基础上，符号位不变，其余各位取反，最后+1。(也即在反码的基础上+1)
     *
     */
}
